﻿using Core.Tools;
using System;

namespace Core.ObjectOperate.ReflectionImpl
{
    /// <summary>
    /// 可快速动态调用的函数委托
    /// </summary>
    public class MethodInfo
    {
        private readonly bool InternalIsPublic;
        private readonly bool InternalIsStatic;
        private readonly string InternalName;
        private readonly Type InternalReturnType;
        private readonly Type[] InternalParamsTypes;
        private readonly IDelegate InternalDelegate;

        public static MethodInfo Create(System.Reflection.MethodInfo Method)
        {
            Type[] ParamsTypes;
            Type ResultType;

            MethodHelper.GetParamsTypes(Method, out ParamsTypes, out ResultType);

            Type Type = MethodHelper.GetDelegateType(ParamsTypes, ResultType);

            Delegate Delegate = Delegate.CreateDelegate(Type, Method);

            return new MethodInfo(Method, (IDelegate)Delegate);
        }

        /// <summary>
        /// 这个函数是否是公开的
        /// </summary>
        public bool IsPublic
        {
            get
            {
                return InternalIsPublic;
            }
        }

        /// <summary>
        /// 函数名称
        /// </summary>
        public string Name
        {
            get
            {
                return InternalName;
            }
        }

        /// <summary>
        /// 函数的返回值类型
        /// </summary>
        public Type ReturnType
        {
            get
            {
                return InternalReturnType;
            }
        }

        /// <summary>
        /// 函数的参数类型列表
        /// </summary>
        public Type[] ParamsTypes
        {
            get
            {
                return (Type[])InternalParamsTypes.Clone();
            }
        }


        /// <summary>
        /// 此委托
        /// </summary>
        public Delegate Delegate
        {
            get { return (Delegate)InternalDelegate; }
        }

        /// <summary>
        /// 初始化函数委托
        /// </summary>
        /// <param name="Method">此函数的反射信息</param>
        /// <param name="DelegateType">委托类型</param>
        private MethodInfo(System.Reflection.MethodInfo Method, IDelegate Delegate)
        {
            InternalDelegate = Delegate;

            InternalName = Method.Name;
            InternalReturnType = Method.ReturnType;
            InternalIsStatic = Method.IsStatic;
            InternalParamsTypes = TypeHelper.GetParamsTypes(Method.GetParameters());
            InternalIsPublic = Method.IsPublic;
        }

        /// <summary>
        /// 动态执行此函数
        /// </summary>
        /// <param name="Object">用于调用函数的实例，静态函数可指定为空</param>
        /// <param name="Params">动态参数列表</param>
        /// <returns>返回此函数执行后的返回值。如果此函数返回值为 void，则返回 null。</returns>
        public object Invoke(object Object, object[] Params)
        {
            if (InternalIsStatic)
            {
                return Delegate.DynamicInvoke(Params);
            }
            else
            {
                return InternalDelegate.DynamicInvoke(Object, Params);
            }
        }

        /// <summary>
        /// 动态执行此函数
        /// </summary>
        /// <param name="TypedRef">用于调用函数的实例引用，静态函数可指定为空</param>
        /// <param name="Params">动态参数列表</param>
        /// <returns>返回此函数执行后的返回值。如果此函数返回值为 void，则返回 null。</returns>
        public object Invoke(TypedReference TypedRef, object[] Params)
        {
            if (InternalIsStatic)
            {
                return Delegate.DynamicInvoke(Params);
            }
            else
            {
                return InternalDelegate.DynamicInvoke(TypedRef, Params);
            }
        }

        /// <summary>
        /// 动态执行此函数
        /// </summary>
        /// <param name="Object">用于调用函数的实例引用，不支持静态函数</param>
        /// <param name="Params">动态参数列表</param>
        /// <param name="Value">函数的最后一个参数</param>
        internal object Invoke(object Object, object[] Params, object Value)
        {
            return InternalDelegate.DynamicInvoke(Object, Params, Value);
        }
    }
}